package ar.pegasus.clasificador.gui;

import java.net.InetAddress;
import java.util.Hashtable;

import javax.naming.NamingException;

import org.jdesktop.jdic.tray.TrayIcon;

import ar.pegasus.clasificador.boss.BossAplicacionClasificador;
import ar.pegasus.clasificador.boss.BossEstilosClasificador;
import ar.pegasus.clasificador.engine.business.BossAplicacionClasificadorRemote;
import ar.pegasus.clasificador.util.BeanFactoryClasificadorRemote;
import ar.pegasus.clasificador.vo.AplicacionClasificadorVO;
import ar.pegasus.framework.auditoria.BossError;
import ar.pegasus.framework.boss.BossAccionesGeneral;
import ar.pegasus.framework.boss.BossConfiguracion;
import ar.pegasus.framework.boss.BossImpresion;
import ar.pegasus.framework.componentes.PException;
import ar.pegasus.framework.componentes.error.notificaciones.NotificadorErroresEmailWS;
import ar.pegasus.framework.configuracion.EnumParametros;
import ar.pegasus.framework.facade.api.remote.ConfiguracionFacadeRemote;
import ar.pegasus.framework.templates.config.IConfigClienteManager;
import ar.pegasus.framework.templates.main.PMainTemplate;
import ar.pegasus.framework.templates.main.menu.MenuApariencia;
import ar.pegasus.framework.templates.main.menu.MenuAyuda;
import ar.pegasus.framework.templates.main.menu.MenuImpresion;
import ar.pegasus.framework.util.BeanFactoryGeneralRemote;
import ar.pegasus.framework.util.NetworkUtil;

public abstract class ClasificadorMainTemplate extends PMainTemplate<ClasificadorLoginManager, ClasificadorConfigClienteManager>{
	private static final long serialVersionUID = 1L;
	
	protected MenuImpresion menuImpresion;
	protected MenuApariencia menuApariencia;
	protected MenuAyuda menuAyuda;

	static {
		initSkin();
	}

	/**
	 * Método constructor.
	 * @param idAplicacion El de id de la aplicación.
	 * @param version La versión de la aplicación.
	 * @throws PException 
	 */
	public ClasificadorMainTemplate(int idAplicacion, String version) throws PException {
		super(idAplicacion, version);
		//Agrega menues adicionales
		construirMenues();
	}

	/**
	 * Crea el manager de login utilizado para loguearse a las aplicaciones.
	 * @return Un objeto LoginManager que implementa ILoginManager.
	 */
	protected final ClasificadorLoginManager crearLoginManager() {
		return new ClasificadorLoginManager(idAplicacion);
	}

	/**
	 * Crea el manager para el manejo de la configuración del cliente.
	 * @return Un objeto ConfigClienteManager que implementa IConfigClienteManager.
	 */
	protected final IConfigClienteManager crearConfigClienteManager() {
		return ClasificadorConfigClienteManager.getInstance();
	}

	/** Método llamado antes de la construcción de la ventana principal */
	protected final void preConstruccion() {
		super.preConstruccion();
		//Configura todos los Boss
		configurarAplicacion();
		//Setea la imágen en el diálogo de login
		setLogoLogin(BossEstilosClasificador.getIconoLogin());
	}

	/** Método llamado inmediatamente después de la construcción de la ventana principal 
	 * @throws PException
	 */
	protected final void postConstruccion() throws PException {
		super.postConstruccion();
		//Crea el ícono de la ventana
		setIconoVentana(BossEstilosClasificador.getIconoVentana());
		//Crea el título de la aplicación con el nombre obtenido desde el Portal de Aplicaciones
		crearTitulo();
	}

	/** Método llamado inmediatamente después de que se loguea el usuario 
	 * @throws PException
	 */
	protected final void postLogin() throws PException {
		super.postLogin();
		//Configura las acciones permitidas para el usuario logueado
		try {
			BossAccionesGeneral.configurarAcciones();
		} catch(PException e) {
			BossError.gestionarError("No se pudieron configurar las acciones" , e);
		}
		//Verifica el entorno Producción/Desarrollo
		verificarEntorno();
		//Muestra las sugerencias del día
		try {
			verTipsOfTheDay();
		} catch(PException e) {
			BossError.gestionarError("No se pudieron mostrar los tips del día" , e);
		}
	}

	/**
	 * Devuelve el men� <b>Impresi�n</b>.
	 * @return menuImpresion
	 */
	protected MenuImpresion getMenuImpresion() {
		return menuImpresion;
	}

	/**
	 * Devuelve el men� <b>Apariencia</b>.
	 * @return menuApariencia
	 */
	protected MenuApariencia getMenuApariencia() {
		return menuApariencia;
	}

	/**
	 * Devuelve el men� <b>Ayuda</b>.
	 * @return menuAyuda
	 */
	protected MenuAyuda getMenuAyuda() {
		return menuAyuda;
	}

	/**
	 * Crea un <b>tray icon</b> utilizado para las alarmas.
	 * @param descripcion La descripci�n.
	 * @return Un nuevo tray icon.
	 */
	public TrayIcon crearTrayIcon(String descripcion) {
		return super.crearTrayIcon(BossEstilosClasificador.getIconoVentana(), descripcion);
	}

	/** Inicializa el skin */
	protected static final void initSkin() {
		String configSkin = null;
		//Carga la configuración del skin
		try {
			configSkin = ClasificadorConfigClienteManager.getInstance().cargarConfiguracionSkin();
		} catch(PException e) {
			BossError.gestionarError(e);
		}
		//Si no existe la configuración setea el skin por default
		if(configSkin == null) {
			BossEstilosClasificador.setDefaultSkin(new SkinRojoClasificador());
		} else {
			//Si existe la config. del skin lo setea
			try {
				BossEstilosClasificador.setDefaultSkin(configSkin);
			} catch(PException e) {
				BossError.gestionarError(e);
				BossEstilosClasificador.setDefaultSkin(new SkinModernoClasificador());
			}
		}
		//Finalmente inicializa el skin
		try {
			BossEstilosClasificador.init();
		} catch(PException e) {
			BossError.gestionarError(e);
			System.exit(-1);
		}
	}

	/**
	 *  Configura la aplicación
	 *   
	 ***/
	protected void configurarAplicacion() {
		try {
			BossAplicacionClasificadorRemote bossAplicacion = BeanFactoryClasificadorRemote.getInstance().getBean(BossAplicacionClasificadorRemote.class); 
			AplicacionClasificadorVO aplicacionVet = bossAplicacion.getAplicacionVetVO(idAplicacion);
			BossAplicacionClasificador.getInstance().setAplicacion(aplicacionVet);
			BossConfiguracion.getInstance();
		} catch(PException e) {
			BossError.gestionarError(new PException("Error configurando la aplicación", e));
			System.exit(-1);
		}
		BossError.setNotificadorErrores(NotificadorErroresEmailWS.getInstance(), idAplicacion);
	}

	/*
	 * Construye el título de la aplicación con el nombre de la aplicación del Portal de Aplicaciones
	 * mas el servidor de la BDD que se está utilizando
	 */
	private void crearTitulo() throws PException {
		StringBuffer sb = new StringBuffer(BossAplicacionClasificador.getInstance().getAplicacion().getDescripcion());
		BossImpresion.getInstance().setNombreAplicacion(BossAplicacionClasificador.getInstance().getAplicacion().getDescripcion() + " ");
		BossImpresion.getInstance().setNombreAplicacion(BossAplicacionClasificador.getInstance().getAplicacion().getDescripcion() + " ");
		if(version != null) {
			sb.append(" v").append(version);
		}
		if(!isEntornoProductivo()) {
			sb.append(" - TEST [").append(getJavaNamingProviderUrl()).append("]");
		}
		setTitle(sb.toString());
	}

	/* Se construyen los menúes y se agregan a la barra de menú de la ventana principal */
	private void construirMenues() {
		menuImpresion = new MenuImpresion();
		agregarMenu(menuImpresion, 1);
		menuApariencia = new MenuApariencia(getDesktop());
		agregarMenu(menuApariencia, 2);
		menuAyuda = new MenuAyuda();
		agregarMenu(menuAyuda, 4);
	}

	/* Muestra un mensaje de advertencia si la aplicación está corriendo en el entorno de Desarrollo */
	private void verificarEntorno() throws PException {
//		if(!isEntornoProductivo()) {
//			PJOptionPane.showWarningMessage(VeterinariaMainTemplate.this, "<HTML>La aplicación está corriendo en entorno de Desarrollo/Test.<br>"
//					+ "<b>Todos los datos que cargue o las operaciones que realice no tendrán efecto en el entorno de Producción.</b><br>"
//					+ "<br>Si Ud. tiene problemas para acceder al entorno de Producción por favor comuníquese con Mesa de Ayuda." + "</HTML>", "Advertencia");
//		}
	}

	/* Método helper que devuelve true si la aplicación está corriendo en el entorno productivo */
	private boolean isEntornoProductivo() throws PException {
		String javaNamingProviderUrlProduccion = getConfiguracionFacade().get(EnumParametros.JAVA_NAMING_PROVIDER_URL_PRODUCCION) ;
		String javaNamingProviderUrl = getJavaNamingProviderUrl();
		if(javaNamingProviderUrlProduccion == null) {
			throw new PException("No se pudo obtener el valor de la propiedad java.naming.provider.url de producci�n");
		}
		if(javaNamingProviderUrl == null) {
			throw new PException("No se pudo obtener el valor de la propiedad java.naming.provider.url");
		}
		InetAddress javaNamingProviderUrlProduccionIp = NetworkUtil.getIpEquipo(javaNamingProviderUrlProduccion);
		InetAddress javaNamingProviderUrlIp = NetworkUtil.getIpEquipo(javaNamingProviderUrl);
		return javaNamingProviderUrlIp.equals(javaNamingProviderUrlProduccionIp);
	}

	public String getJavaNamingProviderUrl() throws PException {
		try {
			Hashtable<?,?> initialContextEnvironment = BeanFactoryGeneralRemote.getInstance().getInitialContext().getEnvironment();
			return (String)initialContextEnvironment.get("java.naming.provider.url");
		} catch(NamingException e) {
			e.printStackTrace();
			throw new PException("No se pudo obtener el valor de la propiedad 'java.naming.provider.url'", e);
		}
	}

    @SuppressWarnings("unchecked")
    private ConfiguracionFacadeRemote<EnumParametros> getConfiguracionFacade() throws PException {
                   return BeanFactoryGeneralRemote.getInstance().getBean(ConfiguracionFacadeRemote.class);
    }

	/* Muestra los tips o sugerencias del día */
	private void verTipsOfTheDay() throws PException {
		// TODO: Como es de baja prioridad se deja pendiente de pasar a EJB3
//		if(System.getProperty("verTip") == null || System.getProperty("verTip").equalsIgnoreCase("true")) {
//			TipsOfTheDayDialog tipsDialog = new TipsOfTheDayDialog(this, BossAplicacion.getAplicacion().getIdAplicacion());
//			List tips = tipsDialog.getTips();
//			if(tips != null && !tips.isEmpty()) {
//				tipsDialog.setVisible(true);
//			}
//		}
	}
}
